/**
 * JSBridge 工具类
 * 支持前端调用APP，提供统一的跨平台通信接口
 */

import { ClientType } from '~/types/bridge.d';
import type {
  PlatformType,
  ClientInfo,
  BridgeResponse,
  BridgeCallback,
  BridgeCallOptions,
  BridgeInstance,
} from '~/types/bridge.d';

/**
 * Bridge 通信桥接类 - H5调用APP
 */
class Bridge {
  private clientInfo: ClientInfo;
  private callbackId = 0;
  private callbacks = new Map<string, BridgeCallback>();
  private readonly APP_IDENTIFIERS = [
    'app-webview',
    'yixinliApp',
    'zixunApp',
    'qingsuApp',
    'zixunshiApp',
    'cikeApp',
  ];

  constructor() {
    this.clientInfo = this.detectClient();
    this.setupGlobalCallback();
    return this.createProxy() as any;
  }

  /**
   * 检测客户端环境
   */
  private detectClient(): ClientInfo {
    // 服务端渲染时的默认值
    if (typeof window === 'undefined' || typeof navigator === 'undefined') {
      return {
        type: ClientType.H5,
        platform: 'unknown',
        userAgent: '',
      };
    }

    const userAgent = navigator.userAgent.toLowerCase();

    // UniApp 环境检测
    if (window.__uniapp || userAgent.includes('uni-app')) {
      return {
        type: ClientType.UNIAPP,
        platform:
          (window.uni?.getSystemInfoSync?.()?.platform as PlatformType) ||
          'unknown',
        userAgent,
      };
    }

    // APP 环境检测
    const hasWebkit = !!window.webkit?.messageHandlers;
    const hasAndroid = !!window.android;
    const hasAppIdentifier = this.APP_IDENTIFIERS.some(id =>
      userAgent.includes(id)
    );

    if (hasWebkit || hasAndroid || hasAppIdentifier) {
      return {
        type: ClientType.APP,
        platform: hasWebkit ? 'ios' : hasAndroid ? 'android' : 'unknown',
        userAgent,
      };
    }

    // 默认 H5 环境
    return {
      type: ClientType.H5,
      platform: 'unknown',
      userAgent,
    };
  }

  /**
   * 设置全局回调处理
   */
  private setupGlobalCallback(): void {
    if (typeof window !== 'undefined') {
      (window as any).bridgeCallback = (
        callbackId: string,
        response: BridgeResponse
      ) => {
        const callback = this.callbacks.get(callbackId);
        if (callback) {
          callback(response);
          this.callbacks.delete(callbackId);
        }
      };
    }
  }

  /**
   * 创建代理对象支持动态方法调用
   */
  private createProxy(): any {
    return new Proxy(this, {
      get(target, prop, receiver) {
        if (prop in target || typeof prop === 'symbol') {
          return Reflect.get(target, prop, receiver);
        }

        if (typeof prop === 'string') {
          return (data?: any, options?: BridgeCallOptions) =>
            target.call(prop, data, options);
        }

        return Reflect.get(target, prop, receiver);
      },
    });
  }

  /**
   * 生成唯一回调ID
   */
  private generateCallbackId(): string {
    return `bridge_${++this.callbackId}_${Date.now()}`;
  }

  /**
   * 统一调用原生方法
   */
  public call<T = any>(
    method: string,
    data: any = {},
    options: BridgeCallOptions<T> = {}
  ): Promise<T> {
    return new Promise((resolve, reject) => {
      try {
        const callbackId = this.generateCallbackId();
        const timeout = options.timeout || 10000;

        // 设置回调
        this.callbacks.set(callbackId, (response: BridgeResponse<T>) => {
          if (response.success) {
            options.onSuccess?.(response.data!);
            resolve(response.data!);
          } else {
            const error = response.error || '调用失败';
            options.onError?.(error);
            reject(new Error(error));
          }
        });

        // 设置超时
        setTimeout(() => {
          if (this.callbacks.has(callbackId)) {
            this.callbacks.delete(callbackId);
            const error = `调用超时: ${method}`;
            options.onError?.(error);
            reject(new Error(error));
          }
        }, timeout);

        // 执行调用
        this.executeCall(method, data, callbackId);
      } catch (error) {
        const errorMsg = error instanceof Error ? error.message : '未知错误';
        options.onError?.(errorMsg);
        reject(error);
      }
    });
  }

  /**
   * 执行具体的平台调用
   */
  private executeCall(method: string, data: any, callbackId: string): void {
    const payload = { ...data, callbackId };

    switch (this.clientInfo.platform) {
      case 'ios':
        this.callIOS(method, payload);
        break;
      case 'android':
        this.callAndroid(method, payload);
        break;
      default:
        if (this.clientInfo.type === ClientType.UNIAPP) {
          this.callUniApp(method, payload);
        } else {
          this.mockCall(method, payload);
        }
    }
  }

  /**
   * iOS 平台调用
   */
  private callIOS(method: string, payload: any): void {
    const messageHandlers = window.webkit?.messageHandlers;
    if (messageHandlers?.[method]) {
      messageHandlers[method].postMessage(JSON.stringify(payload));
    } else {
      throw new Error(`iOS方法不存在: ${method}`);
    }
  }

  /**
   * Android 平台调用
   */
  private callAndroid(method: string, payload: any): void {
    if (!window.android) {
      throw new Error('Android bridge 不可用');
    }

    const uri = `jsbridge://bridge/${method}?${JSON.stringify(payload)}`;
    window.prompt(uri, '');
  }

  /**
   * UniApp 平台调用
   */
  private callUniApp(method: string, payload: any): void {
    if (!window.uni) {
      throw new Error('UniApp bridge 不可用');
    }

    window.uni.postMessage({
      data: { method, ...payload },
    });
  }

  /**
   * H5 环境模拟调用
   */
  private mockCall(method: string, payload: any): void {
    console.log(`[Bridge Mock] 调用方法: ${method}`, payload);

    // 模拟异步响应
    setTimeout(() => {
      const response: BridgeResponse = {
        success: true,
        data: { message: `模拟响应: ${method}` },
      };
      if (typeof window !== 'undefined') {
        (window as any).bridgeCallback?.(payload.callbackId, response);
      }
    }, 100);
  }

  // ==================== 公共API ====================

  /**
   * 获取客户端信息
   */
  getClientInfo(): ClientInfo {
    return { ...this.clientInfo };
  }

  /**
   * 检查是否为指定客户端类型
   */
  isClient(type: ClientType): boolean {
    return this.clientInfo.type === type;
  }

  /**
   * 检查是否为APP环境
   */
  isApp(): boolean {
    return this.clientInfo.type === ClientType.APP;
  }

  /**
   * 检查是否为H5环境
   */
  isH5(): boolean {
    return this.clientInfo.type === ClientType.H5;
  }

  /**
   * 销毁实例，清理资源
   */
  destroy(): void {
    this.callbacks.clear();
    if (typeof window !== 'undefined') {
      delete (window as any).bridgeCallback;
    }
  }
}

// 创建全局实例
const bridge = new Bridge();

export default bridge;
export { Bridge };

// 重新导出类型，方便外部使用
export type {
  ClientType,
  PlatformType,
  ClientInfo,
  BridgeResponse,
  BridgeCallback,
  BridgeCallOptions,
  BridgeInstance,
} from '~/types/bridge.d';
